package qc.common.core.json;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import qc.common.core.constants.QCConstant;
import qc.common.core.utils.JsonUtil;
import qc.common.core.utils.StringSplitUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * Json解析器工具，用于从json字符串或json对象中获取指定属性值
 * 暂时使用直接解析，后继可以考虑使用JsonPath进行改进
 *
 * @author QuCheng Tech
 * @since 2024/1/31
 */
public class JsonParserUtil {

    /***
     * 获取json字符串中指定key的字符串值，如果不存在或者错误返回null，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static String getString(String jsonString, String key) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getString(lastNodeName);
                    }
                }
            }
        }

        return null;
    }

    /***
     * 获取json字符串中指定key的Boolean值，如果不存在或者错误返回null，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static Boolean getBoolean(String jsonString, String key) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getBoolean(lastNodeName);
                    }
                }
            }
        }

        return null;
    }

    /***
     * 获取json字符串中指定key的boolean值，如果不存在或者错误使用指定的默认值，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @param defaultValue 指定的默认值
     * @return boolean
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static boolean getBooleanValue(String jsonString, String key, boolean defaultValue) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getBooleanValue(lastNodeName);
                    }
                }
            }
        }

        return defaultValue;
    }

    /***
     * 获取json字符串中指定key的Double值，如果不存在或者错误返回null，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static Double getDouble(String jsonString, String key) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getDouble(lastNodeName);
                    }
                }
            }
        }

        return null;
    }

    /***
     * 获取json字符串中指定key的double值，如果不存在或者错误使用指定的默认值，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @param defaultValue 指定的默认值
     * @return boolean
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static double getDoubleValue(String jsonString, String key, double defaultValue) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getDoubleValue(lastNodeName);
                    }
                }
            }
        }

        return defaultValue;
    }

    /***
     * 获取json字符串中指定key的Integer值，如果不存在或者错误返回null，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @return java.lang.String
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static Integer getInteger(String jsonString, String key) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getInteger(lastNodeName);
                    }
                }
            }
        }

        return null;
    }

    /***
     * 获取json字符串中指定key的int值，如果不存在或者错误使用指定的默认值，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 属性key，支持使用>&*选择节点；
     * @param defaultValue 指定的默认值
     * @return boolean
     * @author QuCheng Tech
     * @since 2024/1/31
     */
    public static int getIntValue(String jsonString, String key, int defaultValue) {
        if (StringUtils.isNotBlank(jsonString) && StringUtils.isNotBlank(key)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            if (jsonObject != null) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                System.out.println("JsonParseUtil getIntValue jsonObject " + jsonObject.toString());
                if (jsonObject != null) {
                    //根据key解析得到最终的节点名称
                    String[] childStrs = StringSplitUtil.Split(key.trim(), QCConstant.CHILD_STRING, true);
                    if (childStrs != null && childStrs.length > 0x0) {
                        String lastNodeName = childStrs[childStrs.length - 1].trim();
                        if (jsonObject.containsKey(lastNodeName))
                            return jsonObject.getIntValue(lastNodeName);
                    }
                }
            }
        }

        return defaultValue;
    }

    /***
     * 获取指定节点下的所有key-value集合，只返回节点的下一级（不包含所有子级）
     *
     * @param jsonString json字符串
     * @param key 属性key，可以为空，如果为空表示获取所有1级节点对象
     * @return java.util.Dictionary<java.lang.String, java.lang.Object>
     * @author QuCheng Tech
     * @since 2024/2/21
     */
    public static HashMap<String, Object> getChildKeyValues(String jsonString, String key) {
        //System.out.println("jsonString=" + jsonString);
        //System.out.println("key=" + key);
        if (StringUtils.isNotBlank(jsonString)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            //System.out.println("jsonObject=" + jsonObject.toJSONString());
            if (jsonObject != null) {
                return getChildKeyValues(jsonObject, key);
            }
        }

        return null;
    }

    /***
     * 获取指定节点下的所有key-value集合，只返回节点的下一级（不包含所有子级）
     *
     * @param jsonObject json对象
     * @param key 属性key，可以为空，如果为空表示获取所有1级节点对象
     * @return java.util.Dictionary<java.lang.String, java.lang.Object>
     * @author QuCheng Tech
     * @since 2024/2/21
     */
    public static HashMap<String, Object> getChildKeyValues(JSONObject jsonObject, String key) {
        if (jsonObject != null) {
            //如果key为空获取json字符串的所有1级节点；如果key不为空获取指定key的下一级节点
            JSONObject obj = jsonObject;
            //最终获取子级数据的父节点名称
            String parentNodeName = null;
            if (StringUtils.isNotBlank(key)) {
                //根据key中是否包含上下级关系>符号获取节点
                int childStringIndex = key.indexOf(QCConstant.CHILD_STRING);
                if (childStringIndex > 0x0) {
                    jsonObject = getJsonObjectByNodeName(jsonObject, key);
                    parentNodeName = key.substring(childStringIndex + 1);
                }
            }


            if (StringUtils.isNotBlank(parentNodeName))
                obj = jsonObject.getJSONObject(parentNodeName);
            //System.out.println("obj=" + obj.toJSONString());

            if (obj != null && obj.size() > 0x0) {
                HashMap<String, Object> result = new HashMap<>();

                // 遍历 JSONObject
                for (Map.Entry<String, Object> entry : obj.entrySet()) {
                    if (StringUtils.isNotBlank(entry.getKey()))
                        result.put(entry.getKey().trim(), entry.getValue());
                }

                return result;
            }
        }

        return null;
    }

    /***
     * 获取json字符串中指定节点值，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param key 指定的名称，支持使用>&*选择节点；为空表示获取根节点的所有子级
     * @return java.util.HashMap<java.lang.String, java.lang.Object>
     * @author QuCheng Tech
     * @since 2024/2/23
     */
    public static HashMap<String, Object> getKeyValues(String jsonString, String key) {
        //System.out.println("jsonString=" + jsonString);
        //System.out.println("key=" + key);
        if (StringUtils.isNotBlank(jsonString)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            //System.out.println("jsonObject=" + jsonObject.toJSONString());
            if (jsonObject != null) {
                return getKeyValues(jsonObject, key);
            }
        }

        return null;
    }

    /***
     * 获取json字符串中指定节点值，支持使用>&*选择节点
     *
     * @param jsonObject json对象
     * @param key 指定的名称，支持使用>&*选择节点；为空表示获取根节点的所有子级
     * @return java.util.HashMap<java.lang.String, java.lang.Object>
     * @author QuCheng Tech
     * @since 2024/2/23
     */
    public static HashMap<String, Object> getKeyValues(JSONObject jsonObject, String key) {
        if (jsonObject != null) {
            //如果传入的获取节点名称为空，表示获取根节点下的所有一级节点对象
            if (StringUtils.isBlank(key))
                return getChildKeyValues(jsonObject, key);

            //根据key中是否包含上下级关系>符号获取节点
            int childStringIndex = key.indexOf(QCConstant.CHILD_STRING);
            //最终获取子级数据的父节点名称
            String parentNodeName = key;
            if (childStringIndex > 0x0) {
                jsonObject = getJsonObjectByNodeName(jsonObject, key);
                parentNodeName = key.substring(childStringIndex + 1);
            }
            //使用同级连接符号进行分隔
            String[] destNodeNames = null;
            //如果指定的不是查询所有节点，对目标参数名称集合进行分隔赋值
            if (!StringUtils.contains(parentNodeName, QCConstant.ALL_STRING))
                destNodeNames = StringSplitUtil.Split(parentNodeName, QCConstant.BROTHER_CONCAT_STRING, true);

            HashMap<String, Object> result = new HashMap<>();
            //如果按父子级关系得到的json节点对象不为空，处理选取参数值的节点信息
            if (jsonObject != null) {
                //按父子级关系选择的参数节点有效，对json字符串进行赋值，方面后面使用
                HashMap<String, Object> paramValues = null;
                if (StringUtils.contains(parentNodeName, QCConstant.ALL_STRING)) {
                    //含有星号*，选择节点的所有下级元素
                    paramValues = getChildKeyValues(jsonObject, null);
                } else {
                    if (destNodeNames != null && destNodeNames.length > 0x0) {
                        paramValues = getKeyValues(jsonObject, destNodeNames);
                    }
                }
                //根据从json对象中获取的参数值结果进行转换处理
                if (paramValues != null && paramValues.size() > 0x0) {
                    for (Map.Entry<String, Object> entry : paramValues.entrySet()) {
                        if (StringUtils.isNotBlank(entry.getKey()))
                            result.put(entry.getKey().trim(), entry.getValue().toString());
                    }
                }
            } else {
                //根据父子级关系选取到的json对象为空，如果指定了参数名称，根据参数名称逐个赋空值
                if (destNodeNames != null && destNodeNames.length > 0x0) {
                    for (String name : destNodeNames) {
                        if (StringUtils.isNotBlank(name))
                            result.put(name.trim(), null);
                    }
                }
            }
            return result;
        }

        return null;
    }

    /***
     * 获取json字符串中指定名称集合的值，在json对象的根节点获取，支持使用>&*选择节点
     *
     * @param jsonString json字符串
     * @param keys 指定的名称，支持使用>&*选择节点；为空表示获取根节点的所有子级
     * @return java.util.HashMap<java.lang.String, java.lang.Object>
     * @author QuCheng Tech
     * @since 2024/2/23
     */
    public static HashMap<String, Object> getKeyValues(String jsonString, String[] keys) {
        //System.out.println("jsonString=" + jsonString);
        //System.out.println("key=" + key);
        if (StringUtils.isNotBlank(jsonString)) {
            JSONObject jsonObject = JsonUtil.toJSONObject(jsonString);
            //System.out.println("jsonObject=" + jsonObject.toJSONString());
            if (jsonObject != null) {
                return getKeyValues(jsonObject, keys);
            }
        }

        return null;
    }

    /***
     * 获取json对象中指定名称集合的值，在json对象的根节点获取，支持使用>&*选择节点
     *
     * @param jsonObject json对象
     * @param keys 指定的名称，支持使用>&*选择节点；为空表示获取根节点的所有子级
     * @return java.util.HashMap<java.lang.String, java.lang.Object>
     * @author QuCheng Tech
     * @since 2024/2/23
     */
    public static HashMap<String, Object> getKeyValues(JSONObject jsonObject, String[] keys) {
        if (jsonObject != null && keys != null && keys.length > 0x0) {
            HashMap<String, Object> result = new HashMap<>();
            //遍历key逐个进行获取
            for (String key : keys) {
                if (StringUtils.isNotBlank(key)) {
                    HashMap<String, Object> keyValues = getKeyValues(jsonObject, key);
                    if (keyValues != null && keyValues.size() > 0x0) {
                        for (Map.Entry<String, Object> entry : keyValues.entrySet()) {
                            if (StringUtils.isNotBlank(entry.getKey()))
                                result.put(entry.getKey().trim(), entry.getValue());
                        }
                    }
                }

            }
            return result;
        }

        return null;
    }

    /***
     * 获取json对象指定的节点对象，指定的节点名称支持使用大于号>表示上下级
     *
     * @param jsonObject json对象
     * @param nodeName 节点名称，使用>表示上下级关系选择
     * @return com.alibaba.fastjson.JSONObject
     * @author QuCheng Tech
     * @since 2024/3/4
     */
    public static JSONObject getJsonObjectByNodeName(JSONObject jsonObject, String nodeName) {
        if (jsonObject != null) {
            if (StringUtils.isNotBlank(nodeName)) {
                //节点名称字符串不为空时进行分解判断处理，节点名称字符串支持上下级选择符号：>
                String[] childStrs = StringSplitUtil.Split(nodeName.trim(), QCConstant.CHILD_STRING, true);
                String nodeParamValueString = null;
                //解析父子级信息：如果得到的数组长度为1表示没有父子级信息，如果数组长度大于1表示有父子级信息--从第1级开始向子级逐级进行选取直到数组的倒数1个元素
                if (childStrs != null && childStrs.length > 0x1) {
                    //按父子级关系选择json节点至数组中的倒数第1个节点
                    for (int i = 0; i < childStrs.length - 1; i++) {
                        //如果前一次得到的json对象已经为null，无法获取下级对象，直接返回
                        if (jsonObject == null)
                            return null;
                        jsonObject = jsonObject.getJSONObject(childStrs[i]);
                    }
                }
            }
            return jsonObject;
        }
        return null;
    }
}
